package com.licheedev.adplayer;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.kk.taurus.playerbase.assist.InterEvent;
import com.kk.taurus.playerbase.entity.DataSource;
import com.kk.taurus.playerbase.event.OnErrorEventListener;
import com.kk.taurus.playerbase.event.OnPlayerEventListener;
import com.kk.taurus.playerbase.widget.BaseVideoView;
import com.licheedev.adplayer.data.AdData;
import com.licheedev.adplayer.data.AdDataHelper;
import com.licheedev.adplayer.loader.ImageLoader;
import com.licheedev.myutils.LogPlus;
import java.net.URI;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.licheedev.adplayer.AdView.SHOW_AD;
import static com.licheedev.adplayer.AdView.SHOW_ERROR;
import static com.licheedev.adplayer.AdView.SHOW_LOADING;
import static com.licheedev.adplayer.AdView.SHOW_NONE;
import static com.licheedev.adplayer.AdView.VISIBLE;

public class AdViewController {

    private static final String TAG = "AdViewController";

    private final Handler mHandler = new Handler(Looper.getMainLooper());
    private final AdView mAdView;
    private final AdPlayer mAdPlayer;
    private final ImageLoader mImageLoader;

    private DataSourceTask mDataSourceTask;

    /** 视屏是否已经在渲染了 */
    private final AtomicBoolean mRenderStarted = new AtomicBoolean(false);

    private AdData mCurrentAdData;
    /** 暂停视频时播放视频的位置 */
    private int mCurrentPosition;

    private final boolean mEnableLog;

    public AdViewController(@NonNull AdView adView, @NonNull AdPlayer adPlayer) {
        mAdView = adView;
        mAdPlayer = adPlayer;
        mImageLoader = AdPlayerConfig.instance().getImageLoader();
        mEnableLog = AdPlayerConfig.instance().isEnableLog();
    }

    private DataSourceTask url2DataSourceWrapper(String url, DataSourceTask.Callback callback) {
        if (AdPlayerConfig.instance().getCacheStrategy()
            == AdPlayerConfig.STRATEGY_FILE_LRU_CACHE) {
            return new DataSourceTask.LruDownTask(callback, url);
        } else {
            return new DataSourceTask.VideoCacheTask(callback, url);
        }
    }

    /** 当前播放控件 */
    private BaseVideoView currentVideoView() {
        return mAdView.currentVideoView();
    }

    /** 当前播放控件 */
    private ImageView currentImageView() {
        return mAdView.currentImageView();
    }

    public void showNone() {
        mAdView.switchView(SHOW_NONE);
        mAdView.stop();
    }

    /**
     * 播放广告
     *
     * @param data
     * @param playingItemSign
     * @param startTime
     */
    public void playItem(AdData data, String playingItemSign, long startTime) {

        mCurrentAdData = data;
        stop();

        // 第一次加载，
        if (mAdPlayer.getAndChangeFirstLoad()) {
            if (mAdView.enableFirstLoadingLayout) {
                mAdView.switchView(SHOW_LOADING);
            } else {
                mAdView.switchView(SHOW_NONE);
            }
        }

        updateState(PlayEvent.EVENT_SET_DATASOURCE, data, startTime);

        if (mEnableLog) {
            LogPlus.i("Play Item=" + data.getURI());
        }

        if (data.getURI() == null) {
            setErrorState(data, startTime);
            return;
        }

        if (isImageData(data)) {
            processImage(null, data, playingItemSign, startTime);
        } else {
            processVideo(null, data, playingItemSign, startTime);
        }
    }

    public void stop() {
        cleanHandlerTasks();
        // 先尝试停掉前一个任务
        if (mDataSourceTask != null) {
            // 取消任务并清空回调
            mDataSourceTask.cancel();
        }
        mAdView.resetPlayerListener();
        currentVideoView().stop();
    }

    public void pause() {
        cleanHandlerTasks();
        // 先尝试停掉前一个任务
        if (mDataSourceTask != null) {
            // 取消任务并清空回调
            mDataSourceTask.cancel();
        }
        currentVideoView().pause();
        mCurrentPosition = currentVideoView().getCurrentPosition();

        //if (mEnableLog) {
        //    LogPlus.e("暂停position=" + mCurrentPosition);
        //}
    }

    public void resume(String playingItemSign, long startTime, boolean resetRender) {
        cleanHandlerTasks();

        AdData currentData = mCurrentAdData;

        if (currentData == null) {
            return;
        }

        if (currentData.getURI() == null) {
            setErrorState(currentData, startTime);
            return;
        }

        if (isImageData(currentData)) {
            processImage(currentImageView(), currentData, playingItemSign, startTime);
        } else {
            if (currentVideoView().isInPlaybackState()) {
                setPlayerListener(currentData, playingItemSign, startTime, currentVideoView());
                if (resetRender) {
                    //if (mEnableLog) {
                    //    LogPlus.e("恢复position=" + mCurrentPosition);
                    //}
                    currentVideoView().updateRender();
                    currentVideoView().start(mCurrentPosition);
                } else {
                    currentVideoView().resume();
                }
            } else {
                stop();
                processVideo(currentVideoView(), currentData, playingItemSign, startTime);
            }
        }
    }

    public void setVolume(float left, float right) {
        mAdView.setVolume(left, right);
    }

    public void destroy() {
        cleanHandlerTasks();
        if (mDataSourceTask != null) {
            // 取消任务并清空回调
            mDataSourceTask.cancel();
        }
        mAdView.resetPlayerListener();
        mAdView.stopPlayback();
    }

    private boolean isImageData(AdData data) {
        // 其他类型的，都按图片处理
        return data.getType() != AdData.TYPE_VIDEO && data.getType() != AdData.TYPE_MUSIC;
    }

    /**
     * 处理加载图片
     *
     * @param data
     * @param playingItemSign
     * @param startTime
     */
    private void processImage(@Nullable ImageView imageView, AdData data, String playingItemSign,
        long startTime) {

        ImageView contentView;
        if (imageView == null) {
            mAdView.changeImageView();
            contentView = mAdView.currentImageView();
        } else {
            contentView = imageView;
        }

        // 把内容布局放到 ContentIndex的位置
        mAdView.moveContentViewToAdContentIndex(contentView);
        contentView.setVisibility(VISIBLE);

        mImageLoader.loadImage(contentView, data, new ImageLoader.Callback() {
            @Override
            public void onSuccess() {

                if (mAdPlayer.isOutData(playingItemSign)) {
                    return;
                }

                mAdView.makeOtherGone(contentView);
                mAdView.switchView(SHOW_AD);

                // 更新状态
                updateState(PlayEvent.EVENT_IMAGE_PREPARED, data, startTime);

                long delay = data.duration() > 0 ? data.duration() : mAdPlayer.getImageDuration();

                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (mAdPlayer.isOutData(playingItemSign)) {
                            return;
                        }
                        // 发送播放完成
                        updateState(PlayEvent.EVENT_IMAGE_PLAY_COMPLETE, data, startTime);
                    }
                }, delay);
            }

            @Override
            public void onFailure(Exception ex) {

                if (mAdPlayer.isOutData(playingItemSign)) {
                    return;
                }

                setErrorState(data, startTime);
            }
        });
    }

    /**
     * 处理加载视频
     *
     * @param data
     * @param playingItemSign
     * @param startTime
     */
    @SuppressLint("StaticFieldLeak")
    private void processVideo(@Nullable BaseVideoView videoView, AdData data,
        String playingItemSign, long startTime) {

        BaseVideoView contentView;
        if (videoView == null) {
            mAdView.changeVideoView();
            contentView = mAdView.currentVideoView();
        } else {
            contentView = videoView;
        }

        // 把内容布局放到 ContentIndex的位置
        mAdView.moveContentViewToAdContentIndex(contentView);
        contentView.setVisibility(VISIBLE);

        mRenderStarted.set(false);

        setPlayerListener(data, playingItemSign, startTime, contentView);

        URI uri = data.getURI();
        @AdData.Scheme String scheme = uri.getScheme().toLowerCase();

        switch (scheme) {
            case AdData.SCHEME_HTTP:
            case AdData.SCHEME_HTTPS: {
                String url = AdDataHelper.toUrl(uri);
                mDataSourceTask = url2DataSourceWrapper(url, new DataSourceTask.Callback() {
                    @Override
                    public void beforeGetDataSource() {
                        if (mAdPlayer.isOutData(playingItemSign)) {
                            return;
                        }
                        // 显示加载
                        mAdView.switchView(SHOW_LOADING);
                    }

                    @Override
                    public void getDataSourceSuccess(DataSource dataSource) {
                        if (mAdPlayer.isOutData(playingItemSign)) {
                            return;
                        }
                        //LogPlus.i("文件路径=" + dataSource.getData());
                        startPlay(contentView, dataSource);
                    }

                    @Override
                    public void getDataSourceFailure() {
                        if (mAdPlayer.isOutData(playingItemSign)) {
                            return;
                        }
                        LogPlus.w("文件下载失败，url=" + url);
                        // 切换错误
                        setErrorState(data, startTime);
                    }
                });

                mDataSourceTask.start();
                break;
            }
            case AdData.SCHEME_FILE: {
                DataSource dataSource = new DataSource(AdDataHelper.toFilePath(uri));
                startPlay(contentView, dataSource);
                break;
            }
            case AdData.SCHEME_RAW: {
                DataSource dataSource = new DataSource();
                dataSource.setRawId(AdDataHelper.toRawId(uri));
                startPlay(contentView, dataSource);
                break;
            }
            case AdData.SCHEME_ASSET: {
                DataSource dataSource = new DataSource();
                dataSource.setAssetsPath(AdDataHelper.toAsset(uri));
                startPlay(contentView, dataSource);
                break;
            }
            default:
                startPlay(contentView, new DataSource(""));
                break;
        }
    }

    /** 配置播放器监听器 */
    private void setPlayerListener(AdData data, String playingItemSign, long startTime,
        BaseVideoView contentView) {
        // 为了能追踪playingItemSign，每次播放都重新设置监听器
        contentView.setOnPlayerEventListener(new OnPlayerEventListener() {
            @Override
            public void onPlayerEvent(int eventCode, Bundle bundle) {

                if (mEnableLog) {
                    if (bundle != null) {
                        LogPlus.i("onPlayerEvent",
                            "eventCode=" + getEventName(eventCode) + ",bundle=" + bundle);
                    } else {
                        LogPlus.i("onPlayerEvent", "eventCode=" + getEventName(eventCode));
                    }
                }

                if (mAdPlayer.isOutData(playingItemSign)) {
                    return;
                }

                switch (eventCode) {
                    case OnPlayerEventListener.PLAYER_EVENT_ON_AUDIO_DECODER_START:
                        if (data.getType() != AdData.TYPE_MUSIC) {
                            break;
                        }
                    case OnPlayerEventListener.PLAYER_EVENT_ON_VIDEO_RENDER_START:
                        if (mRenderStarted.compareAndSet(false, true)) {

                            mAdView.makeOtherGone(contentView);
                            mAdView.switchView(SHOW_AD);

                            updateState(PlayEvent.EVENT_VIDEO_PREPARED, data, startTime);
                        }
                        break;
                    case OnPlayerEventListener.PLAYER_EVENT_ON_PLAY_COMPLETE:
                        updateState(PlayEvent.EVENT_VIDEO_PLAY_COMPLETE, data, startTime);
                        break;
                }
            }
        });

        contentView.setOnErrorEventListener(new OnErrorEventListener() {
            @Override
            public void onErrorEvent(int eventCode, Bundle bundle) {

                LogPlus.w("onErrorEvent", "eventCode=" + getEventName(eventCode));

                if (mAdPlayer.isOutData(playingItemSign)) {
                    return;
                }
                setErrorState(data, startTime);
            }
        });
    }

    /**
     * 更新状态
     */
    public void updateState(@PlayEvent.Event int state, AdData adData, long startTime) {
        mAdPlayer.updateState(state, adData, startTime);
    }

    /** 设置错误状态 */
    public void setErrorState(AdData data, long startTime) {
        // 显示错误
        mAdView.switchView(SHOW_ERROR);
        // 更新状态
        updateState(PlayEvent.EVENT_PLAY_ERROR, data, startTime);
    }

    /**
     * 清除Handler未执行的任务
     */
    private void cleanHandlerTasks() {
        mHandler.removeCallbacksAndMessages(null);
    }

    private void startPlay(BaseVideoView videoContent, DataSource dataSource) {
        videoContent.setDataSource(dataSource);
        videoContent.start(0);
    }

    /**
     * 根据事件编码获取事件名称定义
     *
     * @param eventCode
     * @return
     */
    private static String getEventName(int eventCode) {

        StringBuilder txt = new StringBuilder();

        String fieldName =
            Util.getFieldName(eventCode, OnPlayerEventListener.class, OnErrorEventListener.class,
                InterEvent.class);
        if (fieldName == null) {
            fieldName = "UNKNOWN_EVENT_CODE";
        }

        txt.append(fieldName).append("(").append(eventCode).append(")");
        return txt.toString();
    }
}
